/**
 * Copyright (c) 2010-2020 by skzr.org
 * All rights reserved.
 * @Author skzr.org(E-mail:skzr.org@gmail.com)
 * @date Jul 19, 2010 11:32:11 PM
 */
package org.skzr.framework.util;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;

/**
 * 提供时区等的支持
 * @author skzr.org(E-mail:skzr.org@gmail.com)
 * @version 1.0.0
 */
public abstract class UtilDate {
	private static final Map<String, TimeZone> timeZoneMap = new HashMap<String, TimeZone>();
	private static final Map<String, Map<String, DateFormat>> dateFormatMap = new HashMap<String, Map<String, DateFormat>>();
	private static final String DEFAULT_FORMAT_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS z";
	private static final transient ThreadLocal<Long> startTime = new ThreadLocal<Long>();
	
	public static Long startTimer() {
		Long v = Long.valueOf(System.currentTimeMillis());
		startTime.set(v);
		return v;
	}
	public static long howTimer() {
		Long start = startTime.get();
		if (start == null) {
			start = startTimer();
		}
		
		return System.currentTimeMillis() - start;
	}
	
	/**
	 * 获取系统缺省时区
	 * @return 缺省时区
	 */
	public static TimeZone getTimeZone() {
		return getTimeZone(null);
	}
	/**
	 * 获取时区对象<br>
	 * 	注意：外部不应当修改此数据
	 * @param id 此时区的 ID "America/Los_Angeles" or "GMT+8:00",null 则是系统运行所在时区
	 * @see TimeZone
	 * @return 指定id的时区
	 */
	public static TimeZone getTimeZone(String id) {
		if (id == null) {
			return getTimeZone(TimeZone.getDefault().getID());
		}
		
		TimeZone ret = timeZoneMap.get(id);
		if (ret == null) {
			synchronized (timeZoneMap) {
				ret = timeZoneMap.get(id);
				if (ret == null) {
					TimeZone o = TimeZone.getTimeZone(id);
					ret = o;
					timeZoneMap.put(id, ret);
				}
			}
		}
		return ret;
	}
	
	/**
	 * 获取系统提供的基础格式化类
	 * 注意：在应用中不应当修改此对象
	 * @param formatPattern null使用DEFAULT_FORMAT_PATTERN
	 * @param timeZone 格式化时的目标时区 null使用getTimeZone()
	 * @return 指定时区，缓存的DateFormat对象
	 */
	public static DateFormat getFormater(String formatPattern, TimeZone timeZone) {
		if (formatPattern == null) {
			formatPattern = DEFAULT_FORMAT_PATTERN;
		}
		
		Map<String, DateFormat> map = dateFormatMap.get(formatPattern);
		if (map == null) {
			synchronized (dateFormatMap) {
				map = dateFormatMap.get(formatPattern);
				if (map == null) {
					Map<String, DateFormat> tmp = new HashMap<String, DateFormat>();
					map = tmp;
					dateFormatMap.put(formatPattern, map);
				}
			}
		}
		
		timeZone = getTimeZone(timeZone == null ? null : timeZone.getID());
		DateFormat ret = map.get(timeZone.getID());
		if (ret == null) {
			synchronized (map) {
				ret = map.get(timeZone.getID());
				if (ret == null) {
					SimpleDateFormat o = new SimpleDateFormat(formatPattern);
					o.setTimeZone(timeZone);
					ret = o;
					map.put(timeZone.getID(), ret);
				}
			}
		}
		return ret;
	}
	
	/**
	 * 获取系统提供的基础格式化类
	 * 注意：在应用中不应当修改此对象
	 * @param formatPattern
	 * @return 默认时区，缓存的DateFormat对象
	 */
	public static DateFormat getFormater(String formatPattern) {
		return getFormater(formatPattern, null);
	}
	
	public static String format(Date date) {
		return format(date, null, null);
	}
	/**
	 * 时间格式化 
	 * @param date 被格式化时间
	 * @param formatPattern 格式化格式
	 * @return 时间的格式化输出
	 */
	public static String format(Date date, String formatPattern) {
		return format(date, formatPattern, null);
	}
	public static String format(Date date, TimeZone timeZone) {
		return format(date, null, timeZone);
	}
	
	/**
	 * 时间格式化 
	 * @param date 被格式化时间
	 * @param formatPattern 格式化格式
	 * @param timeZone 目标时区
	 * @return 时间的格式化输出
	 */
	public static String format(Date date, String formatPattern, TimeZone timeZone) {
		return UtilDate.getFormater(formatPattern, timeZone).format(date);
	}
	
	public static Date parser(String value, String formatPattern) {
		return parser(value, formatPattern, null);
	}
	public static Date parser(String value, String formatPattern, TimeZone timeZone) {
		if (value == null) {
			return null;
		}
		
		try {
			return getFormater(formatPattern, timeZone).parse(value);
		} catch (ParseException e) {
			throw new IllegalArgumentException("转换日期出错(" + value + "," + formatPattern + ",timeZone:" + timeZone + ")", e);
		}
	}
	
	/**
	 * 获取参考时间所在日期的 指定时间点
	 * @param date	参考时间
	 * @param timeOfDay 一天中的时间(格式HH:mm:ss.SSS)
	 * @return
	 */
	public static Date getTimeOfDay(Date date, String timeOfDay) {
		if (timeOfDay != null) timeOfDay = timeOfDay.trim();
		if (timeOfDay == null) return parser(format(date, "yyyy-MM-dd"), "yyyy-MM-dd");
		
		StringBuilder formater = new StringBuilder("yyyy-MM-dd ");
		
		if (timeOfDay.charAt(0) == '.') {
			formater.append(timeOfDay.length() == 1 ? "." : ".SSS");
		} else {
			String[] tmp = timeOfDay.split(":");
			if (!tmp[0].isEmpty()) formater.append("HH");
			if (tmp.length > 1) {
				formater.append(":");
				if (!tmp[1].isEmpty()) formater.append("mm");
				if (tmp.length > 2) {
					formater.append(":");
					if (!tmp[2].isEmpty()) formater.append("ss");
				}
			}
			if (tmp[tmp.length - 1].lastIndexOf('.') != -1) formater.append(".SSS");
		}
		
		return parser(format(date, "yyyy-MM-dd ") + timeOfDay, formater.toString());
	}
}
